﻿//
// Author: Ruxo Zheng (http://ruxozheng.spaces.live.com/)
//
// This file is distributed under CPOL 1.0 License (http://www.codeproject.com/info/cpol10.aspx).
//

using System;
using System.Text;

namespace RZ.Web
{
    /// <summary>
    /// Simple JScript to parse content only!
    /// </summary>
    sealed class HtmlJScriptContentParser : IHtmlParser
    {
        HtmlLexer parentLexer;
        HtmlJScriptContentLexer lexer;

        Int32 startParseLocation;

        public HtmlJScriptContentParser(HtmlLexer lexer)
        {
            this.parentLexer = lexer;
            this.lexer = new HtmlJScriptContentLexer(lexer);

            this.startParseLocation = lexer.Cursor;
        }

        #region IHtmlParser Members

        public HtmlContent GetNextContent()
        {
            var fullContent = new StringBuilder(this.lexer.Content.Length - this.lexer.Cursor);

            String content;

            while (true)
            {
                if (GetJSContent(out content) || GetText(out content))
                    fullContent.Append(content);
                else
                {
                    Int32 saveCursor = this.lexer.BeginCheck();

                    if (this.lexer.IsEndScript())
                    {
                        this.lexer.CommitCheck(false, saveCursor);
                        break;
                    }

                    throw new HtmlParserException("Unrecognized JS script!", this.lexer.Cursor, this.lexer.Content);
                }
            }

            this.parentLexer.Cursor = this.lexer.Cursor;

            return new HtmlContentText(this.lexer.Content.Substring(this.startParseLocation, this.lexer.Cursor - this.startParseLocation));
        }

        #endregion

        Boolean GetJSContent(out String content)
        {
            return GetLineComment(out content) || GetBlockComment(out content) || GetQuoteText(out content);
        }

        Boolean GetLineComment(out String content)
        {
            Int32 saveCursor = this.lexer.BeginCheck();

            content = String.Empty;

            return this.lexer.CommitCheck(this.lexer.IsBeginLineComment() && this.lexer.GetContentLine(out content), saveCursor);
        }

        Boolean GetBlockComment(out String content)
        {
            Int32 saveCursor = this.lexer.BeginCheck();

            content = String.Empty;

            return this.lexer.CommitCheck(this.lexer.IsBeginBlockComment() && this.lexer.GetBlockCommentText(out content), saveCursor);
        }

        Boolean GetQuoteText(out String content)
        {
            Int32 saveCursor = this.lexer.BeginCheck();

            return this.lexer.CommitCheck(this.lexer.GetQuoteText(out content), saveCursor);
        }

        Boolean GetText(out String content)
        {
            Int32 saveCursor = this.lexer.BeginCheck();

            return this.lexer.CommitCheck(this.lexer.GetText(out content), saveCursor);
        }
    }
}
